<?php

namespace App\Repositories;

use App\Criteria\BaseRequestCriteria;
use App\Criteria\GlobalCriteria;
use Prettus\Repository\Eloquent\BaseRepository as L5BaseRepository;

/**
 * Class BaseRepositoryEloquent.
 *
 * @package namespace App\Repositories;
 */
abstract class BaseRepositoryEloquent extends L5BaseRepository implements BaseRepository
{

    /**
     * @var array
     */
    protected $fieldSortable = [
        'id' => 'desc'
    ];

    /**
     * Boot up the repository, pushing criteria
     */
    public function boot()
    {
        $this->pushCriteria(app(GlobalCriteria::class));
    }

    /**
     * 重写 find 方法
     * 获取model 对象 如果没有数据 则返回 空的model对象 而不是null
     * @param $id
     * @param array $columns
     * User: Zhangxy
     * Date: 2018-08-13
     * @return mixed connection or model
     */
    public function find($id, $columns = ['*'])
    {
        $this->applyCriteria();
        $this->applyScope();
        $model = $this->model->findOrNew($id, $columns);
        $this->resetModel();

        return $this->parserResult($model);
    }

    /**
     * 用主键获取一个model 对象 如果查找不到则抛出异常
     * 因为重写了 repository 库的 find 方法 这里补齐
     * @param $id
     * @param array $columns
     * User: Zhangxy
     * Date: 2018-09-05
     * @return mixed
     */
    public function findOrFail($id, $columns = ['*'])
    {
        return parent::find($id, $columns);
    }

    /**
     * 使用数组 填充 where 条件
     * 参考 BaseRepository applyConditions
     * $conditions = [
     * 'a'=>1,
     * 'b'=>['b','>',2],
     * 'c'=>['c','<',3],
     * 'd'=>['d','whereIn',[1,2,3]],
     * 'e'=>['e','whereNUll'],
     * ];
     * @param array $where
     * User: Zhangxy
     * Date: 2018-08-27
     * @return $this
     */
    public function addConditions(array $where)
    {
        if (!empty($where) && is_array($where)) {
            foreach ($where as $field => $value) {
                if (is_null($value)) {
                    continue;
                }
                if (is_array($value)) {
                    list($field, $condition, $val) = $value;
                    if (false === stripos($condition, 'where')) {
                        // < > 什么的
                        $this->model = $this->model->where($field, $condition, $val);
                    } else {
                        if (is_null($val)) {
                            // where NotNull Null
                            $this->model = $this->model->{$condition}($field);
                        } else {
                            // whereIn whereBetween
                            $this->model = $this->model->{$condition}($field, $val);
                        }
                    }
                } else {
                    // 最正常的
                    $this->model = $this->model->where($field, $value);
                }
            }
        }
        return $this;
    }

    /**
     * 根据where条件更新数据
     * 一定要注意 where条件 可能会影响多行
     * @param array $attributes
     * @param array $where
     * User: Zhangxy
     * Date: 2018-08-27
     * @return bool|int
     */
    public function updateByWhere(array $attributes, array $where)
    {
        $this->addConditions($where);
        return $this->model->update($attributes);
    }

    /**
     * skip
     * @param int $value
     * User: Zhangxy
     * Date: 2018-09-19
     * @return $this
     */
    public function skip($value = 0)
    {
        return $this->offset($value);
    }

    /**
     * take
     * @param int $limit
     * User: Zhangxy
     * Date: 2018-09-19
     * @return $this
     */
    public function take($limit = 0)
    {
        return $this->limit($limit);
    }

    /**
     * offset
     * @param int $value
     * User: Zhangxy
     * Date: 2018-09-19
     * @return $this
     */
    public function offset($value = 0)
    {
        if (!empty($value)) {
            $this->model = $this->model->offset($value);
        }
        return $this;
    }

    /**
     * limit
     * @param int $limit
     * User: Zhangxy
     * Date: 2018-09-19
     * @return $this
     */
    public function limit($limit = 0)
    {
        if (!empty($limit)) {
            $this->model = $this->model->limit($limit);
        }
        return $this;
    }


    /**
     * count
     * User: Zhangxy
     * Date: 2018-08-28
     * @return mixed
     */
    public function count()
    {
        $this->applyCriteria();
        $this->applyScope();
        $model = $this->model->count();
        $this->resetModel();

        return $this->parserResult($model);
    }

    /**
     * max
     * @param $field
     * User: Zhangxy
     * Date: 2018-09-06
     * @return mixed
     */
    public function max($field)
    {
        $this->applyCriteria();
        $this->applyScope();
        $model = $this->model->max($field);
        $this->resetModel();

        return $this->parserResult($model);
    }

    /**
     * min
     * @param $field
     * User: Zhangxy
     * Date: 2018-09-06
     * @return mixed
     */
    public function min($field)
    {
        $this->applyCriteria();
        $this->applyScope();
        $model = $this->model->min($field);
        $this->resetModel();

        return $this->parserResult($model);
    }

    /**
     * avg
     * @param $field
     * User: Zhangxy
     * Date: 2018-09-06
     * @return mixed
     */
    public function avg($field)
    {
        $this->applyCriteria();
        $this->applyScope();
        $model = $this->model->avg($field);
        $this->resetModel();

        return $this->parserResult($model);
    }

    /**
     * sum
     * @param $field
     * User: Zhangxy
     * Date: 2018-09-06
     * @return mixed
     */
    public function sum($field)
    {
        $this->applyCriteria();
        $this->applyScope();
        $model = $this->model->sum($field);
        $this->resetModel();

        return $this->parserResult($model);
    }


    /**
     * 将已经删除的也提取出来
     * User: Zhangxy
     * Date: 2018-08-27
     * @return $this
     */
    public function withTrashed()
    {
        $this->model = $this->model->withTrashed();
        return $this;
    }

    /**
     * 可排序字段
     * User: Zhangxy
     * Date: 2018-08-15
     * @return array
     */
    public function getFieldSortable()
    {
        return $this->fieldSortable;
    }

    /**
     * Retrieve all data of repository, paginated
     *
     * @param null $limit
     * @param array $columns
     * @param string $method
     *
     * @return mixed
     */
    public function paginate($limit = null, $columns = ['*'], $method = "paginate")
    {
        $this->pushCriteria(app(BaseRequestCriteria::class));
        return parent::paginate($limit, $columns, $method);
    }

    /**
     * api使用的分页方法
     * @param null $limit
     * @param array $columns
     * @param string $method
     * User: Zhangxy
     * Date: 2018-08-30
     * @return mixed
     */
    public function apiPaginate($limit = null, $columns = ['*'], $method = "paginate")
    {
        $dataInfo = $this->paginate($limit, $columns, $method);

        // todo Zhangxy  有更好的方法一定要告诉我
        $paginationInfo = $dataInfo->toArray();
        unset($paginationInfo['data']);
        return [
            'pagination_info' => $paginationInfo,
            'data' => $dataInfo->items(),
        ];
    }


}
